//  专门处理时间的模块

/**
 * @method formatTime 方法名称,时间戳转为'yyyy-MM-dd hh:mm:ss'
 * @param {String|Number|null} value 时间戳
 * @param {string | null} fmt 格式化的格式,默认为'yyyy-MM-dd hh:mm:ss'
 * fmt说明: * yyyy:年 * MM:月 * dd:日 * hh:小时 * mm:分钟 * ss:秒 * w:星期 * q:季度
 */
export const formatTime = (
  value: string | number | null = new Date().getTime(),
  fmt: string | null = "yyyy-MM-dd hh:mm:ss"
) => {
  let date = new Date(value as string);
  if ((value as string).toString().length == 10) {
    date = new Date((value as any) * 1000);
  }
  if (isNaN(date.getTime())) {
    return "传入格式有误";
  }
  var o: Record<string, Number> = {
    "M+": date.getMonth() + 1, //月份
    "d+": date.getDate(), //日
    "h+": date.getHours(), //小时
    "m+": date.getMinutes(), //分
    "s+": date.getSeconds(), //秒
    "w+": date.getDay(), //星期
    "q+": Math.floor((date.getMonth() + 3) / 3), //季度
    S: date.getMilliseconds(), //毫秒
  };
  if (/(y+)/.test(fmt as string))
    fmt = (fmt as string).replace(
      RegExp.$1,
      (date.getFullYear() + "").substr(4 - RegExp.$1.length)
    );
  for (var k in o) {
    if (k === "w+") {
      if (o[k] === 0) {
        fmt = (fmt as string).replace("w", "周日");
      } else if (o[k] === 1) {
        fmt = (fmt as string).replace("w", "周一");
      } else if (o[k] === 2) {
        fmt = (fmt as string).replace("w", "周二");
      } else if (o[k] === 3) {
        fmt = (fmt as string).replace("w", "周三");
      } else if (o[k] === 4) {
        fmt = (fmt as string).replace("w", "周四");
      } else if (o[k] === 5) {
        fmt = (fmt as string).replace("w", "周五");
      } else if (o[k] === 6) {
        fmt = (fmt as string).replace("w", "周六");
      }
    } else if (new RegExp("(" + k + ")").test(fmt as string)) {
      fmt = (fmt as string).replace(
        RegExp.$1,
        RegExp.$1.length === 1
          ? String(o[k])
          : ("00" + String(o[k])).substr(("" + o[k]).length)
      );
    }
  }
  return fmt;
};
/**
 * @method formatTimeAgo 方法名称,时间戳转为'yyyy-MM-dd hh:mm:ss'或者多久前
 * @param {String|Number} value 时间戳
 * @param {String|Boolean} fmt 返回的指定的格式或者是返回多久之前,默认为false
 */
export const formatTimeAgo = (
  value: string | number,
  fmt: string | null = "yyyy-MM-dd hh:mm:ss"
) => {
  // 返回值
  let tips = "";
  let timeData = new Date(value as any).getTime();

  if (timeData.toString().length == 10) timeData *= 1000;
  if (fmt) {
    (tips as any) = formatTime(timeData, fmt as any);
  } else {
    // 如果为null,则格式化当前时间
    if (value === null) value = +new Date();
    if (value && value.toString().length == 10) (value as any) *= 1000;
    let timestamp = +new Date(Number(value));
    let timer = (Number(new Date()) - timestamp) / 1000; //单位秒

    switch (true) {
      // 如果小于5分钟,则返回"刚刚"
      case timer < 5 * 60:
        tips = "刚刚";
        break;
      // 如果小于1小时,则返回"XX分钟前"
      case timer >= 5 * 60 && timer < 60 * 60:
        tips = parseInt("" + timer / 60) + "分钟前";
        break;
      // 如果小于1天,则返回"XX小时前"
      case timer >= 60 * 60 && timer < 60 * 60 * 24:
        tips = parseInt("" + timer / 60 / 60) + "小时前";
        break;
      // 如果小于1个月,则返回"XX天前"
      case timer >= 60 * 60 * 24 && timer < 60 * 60 * 24 * 30:
        tips = parseInt("" + timer / 60 / 60 / 24) + "天前";
        break;
      // 如果小于1年,则返回"XX月前"
      case timer >= 60 * 60 * 24 * 30 && timer < 60 * 60 * 24 * 30 * 12:
        tips = parseInt("" + timer / 60 / 60 / 24 / 30) + "个月前";
        break;
      // 如果大于1年,则返回"XX年前"
      default:
        tips = parseInt("" + timer / 60 / 60 / 24 / 30 / 12) + "年前";
    }
  }
  return tips;
};


const TIME_RANGE_LIST = [
  "day", // 今天
  "yesterday", //昨天
  "tomorrow", //明天
  "week", //本周
  "lastWeek", //最近一周,
  "nextWeek", //下周
  "month", //本月
  "lastMonth", //上月
  "nextMonth", //下月
  "year", //今年
  "sevenDay", //近七天,
  "sevenMonth", //近三月,
  "sixMonth", //近半年,
] as const;
type TimeRangeListType = (typeof TIME_RANGE_LIST)[number];
/**
 * @method getTimeRange 方法名称,获取指定时间的范围
 * @param {String} type 时间类型,默认为"day"
 * @param {String|Number} value 时间戳,默认为当前时间
 * @param {String} fmt 格式化的格式,默认为"yyyy-MM-dd hh:mm:ss"
 * type说明: * day:今天 * yesterday:昨天 * tomorrow:明天 * week:本周 * lastWeek:最近一周 * nextWeek:下周 *  "month", //本月  "lastMonth", //上月"nextMonth", //下月"year", //今年"sevenDay", //近七天,"sevenMonth", //近三月,"sixMonth", //近半年,
 */
export const formatTimeRange = (
  type: TimeRangeListType | null = "day",
  value: number | string | null = new Date().getTime(),
  fmt: string | null = "yyyy-MM-dd hh:mm:ss"
): string | string[] => {
  let range: string[] = [];
  if (type && !TIME_RANGE_LIST.includes(type as TimeRangeListType)) {
    throw new TypeError(
      `type:${type} 不存在,请传入指定的类型:${TIME_RANGE_LIST.join(",")}`
    );
  }
  let date: any = new Date(value as number);
  if (isNaN(date.getTime())) {
    throw new TypeError("请传入时间戳");
  }
  let start: any = "";
  let end: any = "";
  let year = date.getFullYear();
  let month = date.getMonth();
  let day = date.getDate();
  let week = date.getDay();
  let hour = date.getHours();
  let minute = date.getMinutes();
  let second = date.getSeconds();
  let millisecond = date.getMilliseconds();
  switch (type) {
    case "day": // 今天
      start = new Date(year, month, day, 0, 0, 0, 0).getTime();
      end = new Date(year, month, day, 23, 59, 59, 999).getTime();
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
    case "yesterday": // 昨天
      start = new Date(year, month, day - 1, 0, 0, 0, 0).getTime();
      end = new Date(year, month, day - 1, 23, 59, 59, 999).getTime();
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
    case "tomorrow": // 明天
      start = new Date(year, month, day + 1, 0, 0, 0, 0).getTime();
      end = new Date(year, month, day + 1, 23, 59, 59, 999).getTime();
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
    case "week": // 本周
      if (date.getDay() === 0) {
        start = new Date(year, month, day - 6, 0, 0, 0, 0).getTime();
        end = new Date(year, month, day, 23, 59, 59, 999).getTime();
      } else {
        start = new Date(year, month, day - week + 1, 0, 0, 0, 0).getTime();
        end = new Date(year, month, day - week + 7, 23, 59, 59, 999).getTime();
      }
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
    case "lastWeek": // 上周
      if (date.getDay() === 0) {
        start = new Date(year, month, day - 13, 0, 0, 0, 0).getTime();
        end = new Date(year, month, day - 7, 23, 59, 59, 999).getTime();
      } else {
        start = new Date(year, month, day - week + 1 - 7, 0, 0, 0, 0).getTime();
        end = new Date(year, month, day - week, 23, 59, 59, 999).getTime();
      }
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
    case "nextWeek": // 下周
      if (date.getDay() === 0) {
        start = new Date(year, month, day + 1, 0, 0, 0, 0).getTime();
        end = new Date(year, month, day + 7, 23, 59, 59, 999).getTime();
      } else {
        start = new Date(year, month, day - week + 8, 0, 0, 0, 0).getTime();
        end = new Date(year, month, day - week + 14, 23, 59, 59, 999).getTime();
      }
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
    case "month": // 本月
      start = new Date(year, month, 1, 0, 0, 0, 0).getTime();
      end = new Date(year, month + 1, 0, 23, 59, 59, 999).getTime();
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
    case "lastMonth": // 上个月
      start = new Date(year, month - 1, 1, 0, 0, 0, 0).getTime();
      end = new Date(year, month, 0, 23, 59, 59, 999).getTime();
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
    case "nextMonth": // 下个月
      start = new Date(year, month + 1, 1, 0, 0, 0, 0).getTime();
      end = new Date(year, month + 2, 0, 23, 59, 59, 999).getTime();
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
    case "year": // 今年
      start = new Date(year, 0, 1, 0, 0, 0, 0).getTime();
      end = new Date(year, 11, 31, 23, 59, 59, 999).getTime();
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
    case "sevenDay": // 近七天
      start = new Date(
        year,
        month,
        day - 7,
        hour,
        minute,
        second,
        millisecond
      ).getTime();
      end = new Date(
        year,
        month,
        day,
        hour,
        minute,
        second,
        millisecond
      ).getTime();
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
    case "sevenMonth": // 近七天
      start = new Date(
        year,
        month - 3,
        day,
        hour,
        minute,
        second,
        millisecond
      ).getTime();
      end = new Date(
        year,
        month,
        day,
        hour,
        minute,
        second,
        millisecond
      ).getTime();
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
    case "sixMonth": // 近七天
      start = new Date(
        year,
        month - 6,
        day,
        hour,
        minute,
        second,
        millisecond
      ).getTime();
      end = new Date(
        year,
        month,
        day,
        hour,
        minute,
        second,
        millisecond
      ).getTime();
      range = [formatTime(start, fmt) ?? "", formatTime(end, fmt) ?? ""];
      break;
  }
  new Date();

  return range;
};
/**
 * @method getTimeRange 方法名称,倒计时
 * @param {Number} startTime 开始时间,时间戳毫秒单位
 * @param {Number} endTime 结束时间,时间戳毫秒单位
 * type说明: * 传入开始时间和结束时间,返回一个数组,分别是天、时、分、秒
 */
export const formatTimeDown = (startTime: number, endTime: number): any[] => {
  if (!startTime || !endTime) {
    throw new TypeError(`startTime和endTime不能为空`);
  }
  const start = new Date(startTime).getTime();
  const end = new Date(endTime).getTime();
  if (isNaN(start) || isNaN(end)) {
    throw new TypeError('请传入有效的时间单位,startTime和endTime必须为时间戳');
  }
  let distance = end - start;
  if (distance < 0) {
    return []
  }
  const days = Math.floor(distance / (1000 * 60 * 60 * 24));
  distance %= (1000 * 60 * 60 * 24);
  const hours = Math.floor(distance / (1000 * 60 * 60));
  distance %= (1000 * 60 * 60);
  const minutes = Math.floor(distance / (1000 * 60));
  distance %= (1000 * 60);
  const seconds = Math.floor(distance / 1000);
  return [days < 10 ? '0' + days : days, hours < 10 ? '0' + hours : hours, minutes < 10 ? '0' + minutes : minutes, seconds < 10 ? '0' + seconds : seconds]
}
